use hypers::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Extract, Debug)]
#[param]
#[query]
#[body]
struct BadMan<'a> {
    id: i64,
    username: String,
    first_name: &'a str,
    last_name: String,
    lovers: Vec<String>,
}
#[derive(Serialize, Deserialize, Extract, Debug)]
#[param]
#[query]
#[body]
struct GoodMan<'a> {
    id: i64,
    username: &'a str,
    first_name: String,
    last_name: String,
    #[extract(alias("lovers"))]
    lover: String,
}

async fn show(req: Request) -> Response {
    let content = format!(
        r#"<!DOCTYPE html>
    <html>
        <head>
            <title>Parse data</title>
        </head>
        <body>
            <h1>Hello, fill your profile</h1>
            <form action="/{}?username=jobs" method="post">
                <label>First Name:</label><input type="text" name="first_name" />
                <label>Last Name:</label><input type="text" name="last_name" />
                <legend>What is Your Favorite Pet?</legend>
                <input type="checkbox" name="lovers" value="Cats">Cats<br>
                <input type="checkbox" name="lovers" value="Dogs">Dogs<br>
                <input type="checkbox" name="lovers" value="Birds">Birds<br>
                <input type="submit" value="Submit" />
            </form>
        </body>
    </html>
    "#,
        req.param::<&str>("id").unwrap()
    );
    let res = Response::default();
    res.render(Text::Html(content))
}

async fn edit(mut req: Request) -> Result<String> {
    let bad_man = req.extract::<BadMan>().await?;
    Ok(format!("{bad_man:#?}"))
}

#[tokio::main]
async fn main() -> Result<()> {
    let mut root = Router::default();
    root.get("/:id", show); // http://127.0.0.1:7878/11
    root.post("/:id", edit);
    println!("root = {:#?}", root);
    let listener = hypers::TcpListener::bind("127.0.0.1:7878").await?;
    hypers::listen(root, listener).await
}
